package com.tool.emulator.mos6502.instrs;

import com.tool.emulator.common.AccessUnit;
import com.tool.emulator.common.Util;

/**
 * InstrDumper.java @author tl 2011-6-19
 */
public class InstrDumper {
	public final AccessUnit[] mem;
	public int pc;

	public InstrDumper(AccessUnit[] mem) {
		super();
		this.mem = mem;
		this.pc = 0;
	}

	public static void dump(AccessUnit[] mem, int addr) {
		System.out.println(new InstrDumper(mem).dump(addr));
	}

	private int next() {
		int v = get(this.pc++);
		this.pc &= 0xffff;
		return v;
	}

	private int get(int addr) {
		try {
			return mem[addr & 0xffff].directGet() & 0xff;
		} catch (IndexOutOfBoundsException e) {
			System.err.println(e);
			return 0;
		} catch (NullPointerException e) {
			System.err.println(e);
			return 0;
		}
	}

	public String dump() {
		return dump(null).toString();
	}

	public StringBuilder dump(StringBuilder sb) {
		if (sb == null) sb = new StringBuilder();
		sb.append(Util.w2s(this.pc)).append(":  ");
		int code = this.next();
		sb.append(Util.b2s(code));
		Instr instr = Instr.get(code);
		int op = 0;
		int op1 = 0;
		int op2 = 0;
		if (instr != null) {
			if (instr.opLen > 1) {
				op1 = op = next();
				sb.append(' ').append(Util.b2s(op1));
			}
			if (instr.opLen > 2) {
				op2 = next();
				sb.append(' ').append(Util.b2s(op2));
				op += op2 << 8;
			}
		}
		while (sb.length() < 18) sb.append(' ');
		if (instr == null)
			sb.append("???");
		else {
			sb.append(instr.name);
			String ops = instr.addressingMethod.dump(this.pc, op);
			if (ops != null)
				sb.append(" ").append(ops);
		}
		return sb;
	}

	public String dump(int addr) {
		this.pc = addr;
		return this.dump();
	}
}
